#include <iostream>
#include <string>
#include <cstdio>
#include <queue>
#include <pthread.h>
#include "lockGuard.hpp"


const int g_capacity=10;


template<class T>
class  QueueThread
{
    bool Full()
    {
        return _bq.size()==_capacity;
    }
    bool Empty()
    {
        return _bq.size()==0;
    }
public:
    QueueThread(int capacity=g_capacity)
    :_capacity(capacity)
    {
        pthread_mutex_init(&_Mutex,nullptr);
        pthread_cond_init(&_Empty,nullptr);
        pthread_cond_init(&_Full,nullptr);
    }
    //生产者
    void Push(const T in)
    {
        lockGuard _mtx(&_Mutex);
        while(Full()) 
            pthread_cond_wait(&_Full, &_Mutex);
        _bq.push(in);
        pthread_cond_signal(&_Full);
    }
    //消费者
    void Pop(T* out)
    {
        // //1. 先检测当前的临界资源是否能够满足访问条件
        // // pthread_cond_wait: 我们竟然是在临界区中！我是持有锁的！如果我去等待了，锁该怎么办呢？
        // // pthread_cond_wait第二个参数是一个锁，当成功调用wait之后，传入的锁，会被自动释放！
        // // 当我被唤醒时，我从哪里醒来呢？？从哪里阻塞挂起，就从哪里唤醒, 被唤醒的时候，我们还是在临界区被唤醒的啊
        // // 当我们被唤醒的时候，pthread_cond_wait，会自动帮助我们线程获取锁
        // // pthread_cond_wait: 但是只要是一个函数，就可能调用失败
        // // pthread_cond_wait: 可能存在 伪唤醒 的情况
        // while(isQueueFull()) pthread_cond_wait(&Full_, &mtx_);
        // //2. 访问临界资源，100%确定，资源是就绪的！
        // bq_.push(in);
        lockGuard _mtx(&_Mutex);
        while(Full()) pthread_cond_wait(&_Full, &_Mutex);
        *out=_bq.front();
        _bq.pop();
        pthread_cond_signal(&_Full);
        //return out;
    }
    ~QueueThread()
    {
        //销毁函数
        pthread_mutex_destroy(&_Mutex);
        pthread_cond_destroy(&_Empty);
        pthread_cond_destroy(&_Full);
    }
private:
    std::queue<T> _bq;//队列
    size_t _capacity;//最大容积
    pthread_mutex_t _Mutex;//互斥锁
    pthread_cond_t _Empty; // 用它来表示bq 是否空的条件
    pthread_cond_t _Full;  //  用它来表示bq 是否满的条件
};